/*
	Simple Hertzsprung-Russell diagram analiser. v0.3
	Hertzsprung-Russell diagram from http://ru.wikipedia.org
	(Direct link:
	 http://upload.wikimedia.org/wikipedia/ru/6/6b/HRDiagram.png )
	
	by maniak
	2009.06.08
*/

#ifdef WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// temperature scale parameters
const int start_n[9]={0,8,64,130,203,273,365,443,521};
const int end_n[9]={7,63,129,202,272,364,442,520,566};
const int start[9]={0,30000,10000,7500,6000,5000,4000,3000,2000};
const int end[9]={0,10000,7500,6000,5000,4000,3000,2000,1550};
// temperature calculation proc
int temp_calc(int n)
{
	int z_,y_=0;

	for(z_=0;z_<9;z_++)
	if(n<=end_n[z_])
	{
		y_=(int)((double)start[z_]-(double)(start[z_]-end[z_])*((double)(n-start_n[z_])/(double)(end_n[z_]-start_n[z_]+1)));
		return y_;
	}
	return -1;
}
// colour calculation proc
double colour_calc(int n)
{
	double y_;
	if(n>347) n++; //correction (scale is not perfectly linear)
	if(n>238) n++; //correction
	y_=(double)(n-73)/(double)(110*2);
	return y_;
}
// absolute magnitude calculation proc
double am_calc(int n)
{
	double y_;
	if(n>316) n++; //correction (scale is not perfectly linear)
	y_=(double)(n-253)/25.4; //127/5
	return y_;
}
// luminosity calculation proc
double lum_calc(int n)
{
	double y_;
	y_=pow(10,(double)(375-n)/63);
	return y_;
}

// --------- main ---------
int main(int argc,char* argv)
{
// variables
	FILE *f,*f2,*f3;
	unsigned char r,g,b;
	int i,count_array_elems=0,count_dots_in_array=0,count_dots_total=0;
	short flag;
	struct bvebve
	{
	int count;
	unsigned char r,g,b;
	} data[1024];

	printf("Simple Hertzsprung-Russell diagram analiser. v0.3 by maniak\n\n");
// spectral class stat & starDB creation
	//opening diagram
	printf("[?] Opening diagram file [./diag01.bmp] ... ");
	if ((f=fopen("./diag01.bmp","r"))!=NULL) printf("OK\n");
				         else {printf("Error\n");return 1;};
	//creating DB file
	printf("[?] Creating DB file [./statdb.txt]     ... ");
	if ((f2=fopen("./starbd.txt","w"))!=NULL) printf("OK\n");
				         else {printf("Error\n");return 1;};
	//creating stat file
	printf("[?] Creating stat file [./stat.txt]     ... ");
	if ((f3=fopen("./stat.txt","w"))!=NULL) printf("OK\n");
				         else {printf("Error\n");return 1;};
	//analysis
	printf("[i] Analizing diagram                   ... ");
	//skiping BMP header
	for(i=0;i<54;i++) r=fgetc(f);
	//reading 1st pixel
	b=fgetc(f);
	g=fgetc(f);
	r=fgetc(f);
	while(!feof(f))
	{
		flag=0;
		if(((int)r+(int)g+(int)b)>100) // not a bug & not black
		{
			for(i=0;i<count_array_elems;i++)// if class exist increase counter
			{
				if((r==data[i].r)&&(g==data[i].g)&&(b==data[i].b))
				{
					flag=1;
					data[i].count++;
					count_dots_in_array++;
				}
			}
			if (flag==0)// if class not exist then create it
			{
				data[count_array_elems].r=r;
				data[count_array_elems].g=g;
				data[count_array_elems].b=b;
				data[count_array_elems].count=1;
				count_array_elems++;
				count_dots_in_array++;
			}
			// writing DB entry
			// spectral class
			if((r==213)&&(g==  0)&&(b==  0)) fprintf(f2,"M;");
			if((r==255)&&(g==127)&&(b==  0)) fprintf(f2,"K;");
			if((r==255)&&(g==255)&&(b==  0)) fprintf(f2,"G;");
			if((r==255)&&(g==255)&&(b==207)) fprintf(f2,"F;");
			if((r==255)&&(g==255)&&(b==255)) fprintf(f2,"A;");
			if((r==192)&&(g==255)&&(b==255)) fprintf(f2,"B;");
			if((r==117)&&(g==255)&&(b==255)) fprintf(f2,"O;");
			// temperature
			fprintf(f2,"%d;",temp_calc(count_dots_total%568)); //568 - every line +1 pixel. Why?
			// colour
			fprintf(f2,"%.2f;",colour_calc(count_dots_total%568));
			// luminosity
			fprintf(f2,"%.7f;",lum_calc(count_dots_total/568));
			// absolute magnitude
			fprintf(f2,"%.2f",am_calc(count_dots_total/568));
			// DEBUG
			//fprintf(f2," %dx%d %d",count_dots_total%568,count_dots_total/568,count_dots_total);
			// \n
			fprintf(f2,"\n");
			
		}
		//+1 total dots & read next
		count_dots_total++;
		b=fgetc(f);
		g=fgetc(f);
		r=fgetc(f);
	}
	printf("completed\n");
// writing results of statistics
	printf("[i] Writing spectral class statistics   ... ");
	for(i=0;i<count_array_elems;i++)
	{
		fprintf(f3,"(r g b) %4d %4d %4d : %6d  %6.2f%%\n",data[i].r,data[i].g,
		           data[i].b,data[i].count,(double)data[i].count/(double)count_dots_in_array*100);
	}
	fprintf(f3,"-------------------------------------------\n"
	          "(r g b)   *    *    *  : %6d  100.00%%\n",count_dots_in_array);
	printf("OK\n");
// displaing results of statistics
	for(i=0;i<count_array_elems;i++)
	{
		printf("    (r g b) %4d %4d %4d : %6d  %6.2f%%\n",data[i].r,data[i].g,
		           data[i].b,data[i].count,(double)data[i].count/(double)count_dots_in_array*100);
	}
	printf("    -------------------------------------------\n"
	       "    (r g b)   *    *    *  : %6d  100.00%%\n",count_dots_in_array);

// closing files
	printf("[?] Closing diagram [./diag01.bmp]      ... ");
	if (fclose(f)==0) printf("OK\n");
	             else printf("Error\n");
	printf("[?] Saving DB [./statbd.txt]            ... ");
	if (fclose(f2)==0) printf("OK\n");
	              else printf("Error\n");
	printf("[?] Saving statistics [./stat.txt]      ... ");
	if (fclose(f3)==0) printf("OK\n");
	             else printf("Error\n");
// exiting
	return 0;
}
